import BrukerMRI as bruker
import pylab as pl
import plot
#Python method of extracting raw Bruker Files
import BrukerMRI as bruker
# Modules
import pandas as pd
import pydicom as dcm
import math
import numpy as np
import matplotlib.pyplot as plt
import glob
from os.path import expanduser
import os
from matplotlib import cm
import cmath
# copy and paste entire directory but replace "\" with "/"
# Place a "/" at the end of the line
MainDir = "C:/Users/daniala/Desktop/mri/20191210_104049_MRMD_phantom_practice_1_3/"
ExpNum = 8
Experiment = bruker.ReadExperiment(MainDir, ExpNum)
acqp = Experiment.acqp
method = Experiment.method
raw_fid = Experiment.raw_fid
k_space_gen = Experiment.GenerateKspace()
k_space = Experiment.k_data
k_sp = bruker.phase_shift(120,0,k_space)[:,:,0]
plots = {'Reconstructed k-Space': k_sp}
plot.comparison_k_plots(plots)
Partial Fourier imaging techniques are reconstruction methods in which data from as little as one-half of k-space is used to generate an entire MR since k-space possesses a peculiar mirrored property known as conjugate (or Hermitian) symmetry.
def half_k_space(k_sp,upper_or_lower):
k_space = k_sp.copy()
k_sp_half = np.zeros(k_sp.shape,dtype ='complex')
start = 0
end = 0
if upper_or_lower == "up":
start = 0
end = int(k_space.shape[0]/2)
elif upper_or_lower == "lower":
start = int(k_sp.shape[0]/2)
end = k_space.shape[0]
for i in range(start,end):
k_sp_half[i,:] = k_space[i,:]
return k_sp_half
plots_1 = {'Reconstructed k-Space': k_sp,
'Upper Half of K-space Only': half_k_space(k_sp,'up'),
'Lower Half of K-space Only': half_k_space(k_sp,'lower')
}
plot.comparison_k_plots(plots_1)
Conjugate symmetry applies to pairs of points (like P and Q) that are located diagonally from each other across the origin of k-space. If the data at P is the complex number [a+bi], the data at Q is immediately known to be P's complex conjugate, [a−bi]. Provided no phase errors occur during data collection, k-space possesses a peculiar mirrored property known as conjugate (or Hermitian) symmetry.
def conjugate_sym_test(x,y):
x_1 = x
y_1 = y
P = k_sp[x_1,y_1]
Q = k_sp[255-x,255-y]
print('The value of P in K-sapce is: '+ str(P))
print('The value of Q in K-sapce is: '+ str(Q))
p_r = int(P.real)
q_r = int(Q.real)
p_i = int(P.imag)
q_i = int(Q.imag)
if (p_r == q_r & p_i == (-1*q_i)):
print('P and Q are Hermation Conjugate Pairs')
else:
print('P and Q are NOT Hermation Conjugate Pairs')
conjugate_sym_test(50,50)
conjugate_sym_test(0,0)
def partial_fourier(k_sp,upper_or_lower,percentage):
k_space = k_sp.copy()
frac = percentage/100
k_sp_frac = np.zeros(k_sp.shape,dtype ='complex')
start = 0
end = 0
if upper_or_lower == "up":
start = 0
end = int(frac*(int(k_space.shape[0])-1))
elif upper_or_lower == "lower":
start = k_space.shape[0]-int(frac*(int(k_space.shape[0])-1))
end = k_space.shape[0]
for i in range(start,end):
k_sp_frac[i,:] = k_space[i,:]
return k_sp_frac
plots_3 = {
'60% of upper K-space Only':partial_fourier(k_sp,'up',60),
'60% of Lower K-space Only': partial_fourier(k_sp,'lower',60),
}
plots_3_1 = {
'70% of upper K-space Only':partial_fourier(k_sp,'up',70),
'70% of Lower K-space Only': partial_fourier(k_sp,'lower',70)
}
plot.comparison_k_plots(plots_3)
plot.comparison_k_plots(plots_3_1)
Current partial acquisitions aqcuire more than half of k-sapce to retain ther image contrasts whilst loosing image details from the periphery of k-space.
upper = half_k_space(k_sp,'up')
def hermatian_symmetry_from_half(k_sp):
k_space = k_sp.copy()
k_sp_half = np.zeros(k_space.shape,dtype ='complex')
# top half remains unchanged
k_sp_half[0:128,:] = k_space[0:128,:]
# take the upper left and upper right quarters and reverse the order of the columns
for i in range(0,127):
for j in range(0,127):
k_sp_half[255-i,127-j] = np.conjugate(k_space[i,128+j])
k_sp_half[255-i,128+j] = np.conjugate(k_space[i,127-j])
k_sp_half[128,127:0:-1] = np.conjugate(k_space[127,128:255])
k_sp_half[128,128:255] = np.conjugate(k_space[127,127:0:-1])
return k_sp_half
upper_symmetry = hermatian_symmetry_from_half(k_sp)
plots_4 = {
'Upper Half of K-space Only': upper,
'Conjugate of Ideal Upper Half of K-space': upper_symmetry
#'Lower Half of K-space Only': lower,
#'Conjugate of Lower Half of K-space': conj_lower
}
plot.comparison_k_plots(plots_4)
k_sp_60 = partial_fourier(k_sp,'up',60)
def conjugate_corrections(k_sp,percentage):
k_space = k_sp.copy()
k_sp_conj = np.zeros(k_space.shape,dtype ='complex')
# top half remains unchanged
frac = percentage/100
row = int(frac*(int(k_space.shape[0])))
k_sp_conj[0:row,:] = k_space[0:row,:]
empty_rows = (256-row)
# extracting information from the top and obtaining conjugates
for i in range(0,empty_rows):
for j in range(255):
k_sp_conj[255-i,255-j] = np.conjugate(k_space[i,j])
'''
for j in range(0,127):
k_sp_conj[255-i,127-j] = np.conjugate(k_space[i,128+j])
k_sp_conj[255-i,128+j] = np.conjugate(k_space[i,127-j])
'''
return k_sp_conj
k_sp_conj_60 = conjugate_corrections(k_sp,60)
plots_5 = {
'60% of K-space Only': k_sp_60,
'Conjugate of remaining 40%': k_sp_conj_60
#'Lower Half of K-space Only': lower,
#'Conjugate of Lower Half of K-space': conj_lower
}
plot.comparison_k_plots(plots_5)
k_sp_55 = partial_fourier(k_sp,'up',55)
k_sp_conj_55 = conjugate_corrections(k_sp,55)
plots_6 = {
'55% of K-space Only': k_sp_55,
'Conjugate of remaining 45%': k_sp_conj_55
#'Lower Half of K-space Only': lower,
#'Conjugate of Lower Half of K-space': conj_lower
}
plot.comparison_k_plots(plots_6)
k_sp_50 = partial_fourier(k_sp,'up',50)
k_sp_conj_50 = conjugate_corrections(k_sp,50)
plots_7 = {
'50% of K-space Only': k_sp_50,
'Conjugate of remaining 50%': k_sp_conj_50
#'Lower Half of K-space Only': lower,
#'Conjugate of Lower Half of K-space': conj_lower
}
plot.comparison_k_plots(plots_7)
k_sp_70 = partial_fourier(k_sp,'up',70)
k_sp_conj_70 = conjugate_corrections(k_sp,70)
plots_8 = {
'70% of K-space Only': k_sp_70,
'Conjugate of remaining 30%': k_sp_conj_70
#'Lower Half of K-space Only': lower,
#'Conjugate of Lower Half of K-space': conj_lower
}
plot.comparison_k_plots(plots_8)